using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using OsdmSoftware.CommonLibrary;

namespace OsdmSoftware.PocketPicture
{
    class RotateLeftAction: Action
    {
        public RotateLeftAction()
        {
            this.Name = "Rotate left";
            this.ImageName = "RotateLeftAction";
            this.ParentName = "Selection2";
            this.Hint = "Rotate selection left\r\n(counterclockwise)";
        }

        public override void DoAction()
        {
            if (Form.Mode is SelectionTool)
            unsafe {
                SelectionTool st = (SelectionTool) Form.Mode;
                bool wasNoSelection = false;
                if (st.State == SelectionTool.StateType.NoSelection || st.State == SelectionTool.StateType.HasFirstPoint)
                {
                    st.SelectAll();
                    wasNoSelection = true;
                    //MessageBox.Show("Select an area to rotate");
                    //return;
                }

                Bitmap newBmp = new Bitmap(st.Selection.Height, st.Selection.Width, PixelFormat.Format32bppRgb);
                BitmapData targetData = newBmp.LockBits(new Rectangle(0, 0, st.Selection.Height, st.Selection.Width), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
                BitmapData sourceData = st.Selection.LockBits(new Rectangle(0, 0, st.Selection.Width, st.Selection.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);

                byte* sourceRow = (byte *) sourceData.Scan0.ToPointer();
                for (int y = 0; y < st.Selection.Height; y++, sourceRow += sourceData.Stride)
                {
                    ColorBgra* sourcePixel = (ColorBgra*) sourceRow;
                    for (int x = 0; x < st.Selection.Width; x++, sourcePixel ++)
                    {
                        int newX = y;
                        int newY = st.Selection.Width - 1 - x;

                        byte* targetRow = ((byte*) targetData.Scan0.ToPointer()) + targetData.Stride * newY;
                        ColorBgra* targetPixel = ((ColorBgra*) targetRow) + newX;
                        targetPixel->Bgra = sourcePixel->Bgra;
                    }
                }

                st.Selection.UnlockBits(sourceData);
                newBmp.UnlockBits(targetData);

                Graphics gr = Graphics.FromImage(Form.BitmapZoomer.Bitmap);
                st.ClearSelection(gr);
                gr.Dispose();
                st.Selection.Dispose();
                st.Selection = null;

                st.SelectTool();
                st.State = SelectionTool.StateType.CopySelection;
                Form.BitmapZoomer.SelectionRect = new Rectangle(Form.BitmapZoomer.SelectionRect.X, Form.BitmapZoomer.SelectionRect.Y, newBmp.Width, newBmp.Height);
                st.Selection = newBmp;
                st.CopyOrMoveSelection(Form.BitmapZoomer.SelectionRect.X, Form.BitmapZoomer.SelectionRect.Y);

                if (wasNoSelection)
                    st.Cancel();

                Form.PushToUndo();
                Form.BitmapZoomer.Refresh();
            }
            else
            {
                MessageBox.Show("Select an area to rotate");
            }

            base.DoAction();
        }
    }

    class RotateRightAction: Action
    {
        public RotateRightAction()
        {
            this.Name = "Rotate right";
            this.ImageName = "RotateRightAction";
            this.ParentName = "Selection2";
            this.Hint = "Rotate selection right\r\n(clockwise)";
        }

        public override void DoAction()
        {
            if (Form.Mode is SelectionTool)
                unsafe
                {
                    bool wasNoSelection = false;
                    SelectionTool st = (SelectionTool) Form.Mode;
                    if (st.State == SelectionTool.StateType.NoSelection || st.State == SelectionTool.StateType.HasFirstPoint)
                    {
                        st.SelectAll();
                        wasNoSelection = true;
                        //MessageBox.Show("Select an area to rotate");
                        //return;
                    }

                    Bitmap newBmp = new Bitmap(st.Selection.Height, st.Selection.Width, PixelFormat.Format32bppRgb);
                    BitmapData targetData = newBmp.LockBits(new Rectangle(0, 0, st.Selection.Height, st.Selection.Width), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
                    BitmapData sourceData = st.Selection.LockBits(new Rectangle(0, 0, st.Selection.Width, st.Selection.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);

                    byte* sourceRow = (byte*) sourceData.Scan0.ToPointer();
                    for (int y = 0; y < st.Selection.Height; y++, sourceRow += sourceData.Stride)
                    {
                        ColorBgra* sourcePixel = (ColorBgra*) sourceRow;
                        for (int x = 0; x < st.Selection.Width; x++, sourcePixel++)
                        {
                            int newX = st.Selection.Height - 1 - y;
                            int newY = x;

                            byte* targetRow = ((byte*) targetData.Scan0.ToPointer()) + targetData.Stride * newY;
                            ColorBgra* targetPixel = ((ColorBgra*) targetRow) + newX;
                            targetPixel->Bgra = sourcePixel->Bgra;
                        }
                    }

                    st.Selection.UnlockBits(sourceData);
                    newBmp.UnlockBits(targetData);

                    Graphics gr = Graphics.FromImage(Form.BitmapZoomer.Bitmap);
                    st.ClearSelection(gr);
                    gr.Dispose();
                    st.Selection.Dispose();
                    st.Selection = null;

                    st.SelectTool();
                    st.State = SelectionTool.StateType.CopySelection;
                    Form.BitmapZoomer.SelectionRect = new Rectangle(Form.BitmapZoomer.SelectionRect.X, Form.BitmapZoomer.SelectionRect.Y, newBmp.Width, newBmp.Height);
                    st.Selection = newBmp;
                    st.CopyOrMoveSelection(Form.BitmapZoomer.SelectionRect.X, Form.BitmapZoomer.SelectionRect.Y);

                    if (wasNoSelection)
                        st.Cancel();

                    Form.PushToUndo();
                    Form.BitmapZoomer.Refresh();
                }
            else
            {
                MessageBox.Show("Select an area to rotate");
            }

            base.DoAction();
        }
    }

    class FlipHorizontalAction: Action
    {
        public FlipHorizontalAction()
        {
            this.Name = "Flip horizontally";
            this.ImageName = "FlipHorizontallyAction";
            this.ParentName = "Selection2";
            this.Hint = "Flip selection horizontally";
        }

        public override void DoAction()
        {
            if (Form.Mode is SelectionTool)
                unsafe
                {
                    bool wasNoSelection = false;
                    SelectionTool st = (SelectionTool) Form.Mode;
                    if (st.State == SelectionTool.StateType.NoSelection || st.State == SelectionTool.StateType.HasFirstPoint)
                    {
                        st.SelectAll();
                        wasNoSelection = true;
                        //MessageBox.Show("Select an area to rotate");
                        //return;
                    }

                    Bitmap newBmp = new Bitmap(st.Selection.Width, st.Selection.Height, PixelFormat.Format32bppRgb);
                    BitmapData targetData = newBmp.LockBits(new Rectangle(0, 0, st.Selection.Width, st.Selection.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
                    BitmapData sourceData = st.Selection.LockBits(new Rectangle(0, 0, st.Selection.Width, st.Selection.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);

                    byte* sourceRow = (byte*) sourceData.Scan0.ToPointer();
                    for (int y = 0; y < st.Selection.Height; y++, sourceRow += sourceData.Stride)
                    {
                        ColorBgra* sourcePixel = (ColorBgra*) sourceRow;
                        for (int x = 0; x < st.Selection.Width; x++, sourcePixel++)
                        {
                            int newX = st.Selection.Width - 1 - x;
                            int newY = y;

                            byte* targetRow = ((byte*) targetData.Scan0.ToPointer()) + targetData.Stride * newY;
                            ColorBgra* targetPixel = ((ColorBgra*) targetRow) + newX;
                            targetPixel->Bgra = sourcePixel->Bgra;
                        }
                    }

                    st.Selection.UnlockBits(sourceData);
                    newBmp.UnlockBits(targetData);

                    Graphics gr = Graphics.FromImage(Form.BitmapZoomer.Bitmap);
                    st.ClearSelection(gr);
                    gr.Dispose();
                    st.Selection.Dispose();
                    st.Selection = null;

                    st.SelectTool();
                    st.State = SelectionTool.StateType.CopySelection;
                    Form.BitmapZoomer.SelectionRect = new Rectangle(Form.BitmapZoomer.SelectionRect.X, Form.BitmapZoomer.SelectionRect.Y, newBmp.Width, newBmp.Height);
                    st.Selection = newBmp;
                    st.CopyOrMoveSelection(Form.BitmapZoomer.SelectionRect.X, Form.BitmapZoomer.SelectionRect.Y);

                    if (wasNoSelection)
                        st.Cancel();

                    Form.PushToUndo();
                    Form.BitmapZoomer.Refresh();
                }
            else
            {
                MessageBox.Show("Select an area to rotate");
            }

            base.DoAction();
        }
    }

    class FlipVerticalAction: Action
    {
        public FlipVerticalAction()
        {
            this.Name = "Flip vertically";
            this.ImageName = "FlipVerticallyAction";
            this.ParentName = "Selection2";
            this.Hint = "Flip selection vertically";
        }

        public override void DoAction()
        {
            if (Form.Mode is SelectionTool)
                unsafe
                {
                    bool wasNoSelection = false;
                    SelectionTool st = (SelectionTool) Form.Mode;
                    if (st.State == SelectionTool.StateType.NoSelection || st.State == SelectionTool.StateType.HasFirstPoint)
                    {
                        st.SelectAll();
                        wasNoSelection = true;
                        //MessageBox.Show("Select an area to rotate");
                        //return;
                    }

                    Bitmap newBmp = new Bitmap(st.Selection.Width, st.Selection.Height, PixelFormat.Format32bppRgb);
                    BitmapData targetData = newBmp.LockBits(new Rectangle(0, 0, st.Selection.Width, st.Selection.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
                    BitmapData sourceData = st.Selection.LockBits(new Rectangle(0, 0, st.Selection.Width, st.Selection.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);

                    byte* sourceRow = (byte*) sourceData.Scan0.ToPointer();
                    for (int y = 0; y < st.Selection.Height; y++, sourceRow += sourceData.Stride)
                    {
                        ColorBgra* sourcePixel = (ColorBgra*) sourceRow;
                        for (int x = 0; x < st.Selection.Width; x++, sourcePixel++)
                        {
                            int newX = x;
                            int newY = st.Selection.Height - 1 - y;

                            byte* targetRow = ((byte*) targetData.Scan0.ToPointer()) + targetData.Stride * newY;
                            ColorBgra* targetPixel = ((ColorBgra*) targetRow) + newX;
                            targetPixel->Bgra = sourcePixel->Bgra;
                        }
                    }

                    st.Selection.UnlockBits(sourceData);
                    newBmp.UnlockBits(targetData);

                    Graphics gr = Graphics.FromImage(Form.BitmapZoomer.Bitmap);
                    st.ClearSelection(gr);
                    gr.Dispose();
                    st.Selection.Dispose();
                    st.Selection = null;

                    st.SelectTool();
                    st.State = SelectionTool.StateType.CopySelection;
                    Form.BitmapZoomer.SelectionRect = new Rectangle(Form.BitmapZoomer.SelectionRect.X, Form.BitmapZoomer.SelectionRect.Y, newBmp.Width, newBmp.Height);
                    st.Selection = newBmp;
                    st.CopyOrMoveSelection(Form.BitmapZoomer.SelectionRect.X, Form.BitmapZoomer.SelectionRect.Y);

                    if (wasNoSelection)
                        st.Cancel();

                    Form.PushToUndo();
                    Form.BitmapZoomer.Refresh();
                }
            else
            {
                MessageBox.Show("Select an area to rotate");
            }

            base.DoAction();
        }
    }
}
